package xdu.lz.stage3_classloader.chapter5;

import xdu.lz.stage3_classloader.chapter4.SimpleClassLoader;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 线程上下文类加载器
 * @since 2020/1/5 0005 下午 1:40
 */
public class ThreadContextClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //当前线程使用的是系统类加载器Appclassloader
        System.out.println(Thread.currentThread().getContextClassLoader());
        //改变当前线程使用的类加载器，改为自定义加载器
        Thread.currentThread().setContextClassLoader(new SimpleClassLoader());
        System.out.println(Thread.currentThread().getContextClassLoader());

//        这样做的目的是，解决了 SPI(Service Provicer Interface)接口提供者带来的问题
//        我们知道，jdk定义了很多接口规范 ，不同厂商实现不同。
//        如java.sql包下的Driver接口，定义了数据库连接的规范
//        com.mysql.jdbc.Driver是对java.sql.Driver的实现
//        我们连接数据库写的第一句话就是
//        Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
//        com.mysql.jdbc.Driver内部初始化代码块是
//
//        把自己注册到java.sql的DriverManager下，后面全都是面向接口编程。
//
//        拿连接  为什么能拿到注册的厂商的连接？看源码是遍历注册过的连接，
//         并把线程上下文类加载器设定为ApplicationClassLoader去加载厂商下的类
        Connection connection = DriverManager.getConnection("");
//        如果不这样做，那么会被根加载器BootClassLoader去加载接口 ，但是拿不到任何实例实现，所以没有任何意义。
//        这是一种不得已而为之的破坏双亲委托机制的行为。
//        因为又要面向接口编程，又存在双亲委托，这本来就是矛盾的。

    }
    static {
        try {
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
